package com.zh.blog.strategy.impl;

import com.alibaba.fastjson.JSON;
import com.zh.blog.common.api.StatusCodeEnum;
import com.zh.blog.config.WeiboConfigProperties;
import com.zh.blog.dto.SocialTokenDto;
import com.zh.blog.dto.SocialUserInfoDto;
import com.zh.blog.dto.WeiboTokenDto;
import com.zh.blog.dto.WeiboUserInfoDto;
import com.zh.blog.enums.LoginTypeEnum;
import com.zh.blog.exception.BizException;
import com.zh.blog.vo.WeiboLoginVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import static com.zh.blog.constant.SocialLoginConst.*;

/**
 * 微博登录策略实现
 * @author ZhengHao
 * Created At 2022/8/25.
 **/
@Service("weiboLoginStrategyImpl")
public class WeiboLoginStrategyImpl extends AbstractSocialLoginStrategyImpl{
    @Autowired
    private WeiboConfigProperties weiboConfigProperties;
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public SocialUserInfoDto getSocialUserInfo(SocialTokenDto socialToken) {
        // 定义请求参数
        Map<String, String> data = new HashMap<String, String>(2);
        data.put(UID, socialToken.getOpenId());
        data.put(ACCESS_TOKEN, socialToken.getAccessToken());
        // 获取微博用户信息
        WeiboUserInfoDto weiboUserInfoDto = restTemplate.getForObject(weiboConfigProperties.getUserInfoUrl(), WeiboUserInfoDto.class,data);
        // 返回用户信息
        return SocialUserInfoDto.builder()
                .nickname(Objects.requireNonNull(weiboUserInfoDto).getScreen_name())
                .avatar(weiboUserInfoDto.getAvatar_hd())
                .build();
    }

    @Override
    public SocialTokenDto getSocialToken(String data) {
        WeiboLoginVO weiboLoginVO = JSON.parseObject(data, WeiboLoginVO.class);
        // 获取微博token信息
        WeiboTokenDto weiboToken = getWeiboToken(weiboLoginVO);
        // 返回token信息
        return SocialTokenDto.builder()
                .openId(weiboToken.getUid())
                .accessToken(weiboToken.getAccess_token())
                .loginType(LoginTypeEnum.WEIBO.getType())
                .build();
    }

    /**
     * 获取微博token信息
     * @param weiboLoginVO 微博登录信息
     * @return 微博token
     */
    private WeiboTokenDto getWeiboToken(WeiboLoginVO weiboLoginVO) {
        // 根据code换取微博uid和accessToken
        // Spring的内部实现是LinkedMultiValueMap ,即一个键对应多个值
        LinkedMultiValueMap<String, String> weiboData = new LinkedMultiValueMap<>();
        // 定义微博token请求参数
        weiboData.add(CLIENT_ID,weiboConfigProperties.getAppId());
        weiboData.add(CLIENT_SECRET, weiboConfigProperties.getAppSecret());
        weiboData.add(GRANT_TYPE, weiboConfigProperties.getGrantType());
        weiboData.add(REDIRECT_URI, weiboConfigProperties.getRedirectUrl());
        weiboData.add(CODE, weiboLoginVO.getCode());
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(weiboData, null);
        try {
            return restTemplate.exchange(weiboConfigProperties.getAccessTokenUrl(), HttpMethod.POST, requestEntity, WeiboTokenDto.class).getBody();
        } catch (Exception e) {
            throw new BizException(StatusCodeEnum.WEIBO_LOGIN_ERROR);
        }
    }
}